'''
Description: 
Version: 1.0.1
Autor: hrlu.cn
Date: 2022-07-19 15:33:00
LastEditors: hrlu.cn
LastEditTime: 2022-07-30 14:11:07
'''
import time
from collections import defaultdict

import pandas as pd
from sqlalchemy import create_engine

from processor.models import Logger, MACPool, RSIStructure, RSIExtremum, RSITrend

EXPORT_TYPES = {
    'fail': "标准",
    'replace': "覆盖",
    'append': "追加"
}

class Exporter:
    desp = 'Basic Exporter'

    @property
    def _data(self):
        return None

    def to_db(self, host, port, user, password, db, table, write_type='fail'):
        start_time = time.time()
        engine = create_engine(f'mysql://{user}:{password}@{host}:{port}/{db}?charset=utf8')
        
        df = self._data
        assert isinstance(df, pd.core.frame.DataFrame), "Exporter not ready for writing!"
        
        df.to_sql(table, engine, if_exists=write_type, index=False)
        time_cost = round(time.time() - start_time, 2)
        
        tag = f'''<a href="#" data-toggle="tooltip" title="{host}:{port}/{db}.{table}">{host}</a>'''
        Logger.info(
                    msg=f"源「{self.desp}」导出至 {tag} 完成，"
                        f"共计 {len(df)} 行，耗时 {time_cost} 秒。",
                    module='export'
                   )


class MAExporter(Exporter):
    desp = "MA交叉筛选"

    @property
    def _data(self):
        data = defaultdict(list)

        for record in MACPool.objects.values('field', 'fdate', 'pid'):
            for code, info in record['field'].items():
                data['code'].append(code)
                data['name'].append(info['sname'])
                data['pool_time'].append(info['status'])
                data['trade_date'].append(record['fdate'].strftime('%Y-%m-%d'))
                data['pool_no'].append(record['pid'])

        return pd.DataFrame(data)


class RSIStructureExporter(Exporter):
    desp = "RSI数据分析"

    @property
    def _data(self):
        data = defaultdict(list)

        for record in RSIStructure.objects.values('sdate', 'percentage'):
            if sum(record['percentage']) == 0:
                continue

            data['trade_date'].append(record['sdate'])
            for idx in range(6):
                data[f'r{idx + 1}'].append(record['percentage'][idx])
        
        return pd.DataFrame(data)


class RSIExtremumExporter(Exporter):
    desp = "RSI极值监控"

    @property
    def _data(self):
        data = defaultdict(list)
        # fields = {'rsi_maxd': 8, 'rsi_mind': 4, 'rsi_maxdx': 2, 'rsi_mindx': 1}

        for record in RSIExtremum.objects.values(
            'scode', 'stock_rsi__stock_basic__sname', 'updated_date', 
            'updated_field', 'rsi_maxd', 'rsi_mind', 'rsi_maxdx', 'rsi_mindx'
        ):
            data['code'].append(record['scode'])
            data['name'].append(record['stock_rsi__stock_basic__sname'])
            data['trade_date'].append(record['updated_date'])
            if record['updated_field'] & 8:
                data['history_status'].append(1)
                rsi = record['rsi_maxd']
            elif record['updated_field'] & 4:
                data['history_status'].append(-1)
                rsi = record['rsi_mind']
            else:
                data['history_status'].append(0)
            
            if record['updated_field'] & 2:
                data['period_status'].append(1)
                rsi = record['rsi_maxdx']
            elif record['updated_field'] & 1:
                data['period_status'].append(-1)
                rsi = record['rsi_mindx']
            else:
                data['period_status'].append(0)

            data['rsi'].append(rsi)
        
        return pd.DataFrame(data)


class RSITrendExporter(Exporter):    
    @property
    def _data(self):
        data = []

        period_symbol = 'D' if self.period == 1 else 'W'

        rsi_trend = RSITrend.objects.filter(period=self.period).order_by('fdate')
        record = rsi_trend.values('bg_a', 'bg_b', 'bg_c', 'bg_d').last()

        for k in record:
            for row in record[f'bg_{k[-1]}']:
                data.append({
                    'trend': f'{period_symbol}bg-{k[-1].upper()}',
                    'scode': row['scode'],
                    'sname': row['sname'],
                    'industry': row['industry'],
                    'check_point': row['check_point'].upper(),
                    'check_point_date': row['point_' + row['check_point']]['date'],
                    'check_point_rsi': row['point_' + row['check_point']]['rsi'],
                    'n_rsi': row['point_n']['rsi'],
                })

        return pd.DataFrame(data)


class RSIDailyTrendExporter(RSITrendExporter):
    desp = "RSI趋势判断(日)"
    period = 1

class RSIWeeklyTrendExporter(RSITrendExporter):
    desp = "RSI趋势判断(周)"
    period = 2


EXPORTERS = {
    'MA': {
        'class': MAExporter,
        'desp': MAExporter.desp,
        'table_name': "ma",
    },
    'RSIA': {
        'class': RSIStructureExporter,
        'desp': RSIStructureExporter.desp,
        'table_name': "rsia",
    },
    'EXT': {
        'class': RSIExtremumExporter,
        'desp': RSIExtremumExporter.desp,
        'table_name': "ext",
    },
    'RSIFD': {
        'class': RSIDailyTrendExporter,
        'desp': RSIDailyTrendExporter.desp,
        'table_name': "rsifd",
    },
    'RSIFW': {
        'class': RSIWeeklyTrendExporter,
        'desp': RSIWeeklyTrendExporter.desp,
        'table_name': "rsifw",
    },
}